/*
 * Author: xzy
 * Date: 2025-08-27
 * Time: 15:32:01
 * Description: 用户管理
 */
package com.xtedu.examproject.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.xtedu.examproject.entity.*;
import com.xtedu.examproject.service.*;
import com.xtedu.examproject.util.MenuTreeBuilder;
import com.xtedu.examproject.util.PageHelper;
import com.xtedu.examproject.util.RedisUtil;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@WebServlet("/usermanage/*")
public class UserServlet extends HttpServlet {
    private UserService userService;
    private static final int PAGE_SIZE = 5; // 每页显示的记录数
    private MenuService menuService;
    private StudentService studentService;
    private TeacherService teacherService;
    private RoleService roleService;
    private final Gson gson = new Gson();

    @Override
    public void init() {
        userService = new UserService();
        menuService = new MenuService();
        studentService = new StudentService();
        teacherService = new TeacherService();
        roleService = new RoleService();
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String pathInfo = req.getPathInfo();

        // 处理 null 或空路径
        if (pathInfo == null || pathInfo.equals("/") || pathInfo.isEmpty()) {
            showActive(req, resp);
            return;
        }
        // 标准化路径（去除前导和尾随斜杠）
        String path = pathInfo.replaceAll("^/|/$", "");

        try {
            //从Redis中获取当前用户信息
            HttpSession session = req.getSession();
            User user = RedisUtil.getObject("session:" + session.getId(), User.class);
            if (user == null) {
                user = session.getAttribute("user") == null ? new User() : (User) session.getAttribute("user");
            }

            int roleId = user.getRoleId();
            int userId = user.getId();
            if (session.getAttribute("activeUsers") == null) {
                List<User> activeUsers = switch (roleId) {
                    // 讲师和学生
                    case 1, 4 -> userService.showByOwnClazz(userId);
                    // 教务 - 能看到讲师、教务、学生、辅导员
                    case 2 -> {
                        List<User> users = new ArrayList<>();
                        users.addAll(userService.findByRoleId(1)); // 讲师
                        users.addAll(userService.findByRoleId(2)); // 教务
                        users.addAll(userService.findByRoleId(4)); // 学生
                        users.addAll(userService.findByRoleId(5)); // 辅导员
                        //在switch表达式的这个分支中，创建并填充了一个 users 列表
                        yield users;
                    }
                    // 超级管理员和校长 - 能看到所有用户
                    case 3, 7 -> userService.findAllUser();
                    // 辅导员 - 只能看到学生
                    case 5 -> userService.findByRoleId(4);
                    // 学院院长 - 能看到讲师、教务、辅导员
                    case 6 -> {
                        List<User> users = new ArrayList<>();
                        users.addAll(userService.findByRoleId(1)); // 讲师
                        users.addAll(userService.findByRoleId(2)); // 教务
                        users.addAll(userService.findByRoleId(5)); // 辅导员
                        yield users;
                    }
                    default -> new ArrayList<>();
                };
                session.setAttribute("activeUsers", activeUsers);
            }


        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        switch (path) {
            case "findByRoleId" -> findByRoleId(req, resp);
            case "findById" -> findById(req, resp);
            case "findByUsername" -> findByUsername(req, resp);
            case "showInfo" -> showUserInfo(req, resp);
            case "addUser" -> getRoleList(req, resp);
            case "showUser" -> getUserList(req, resp);
            case "deleteUser" -> deleteUser(req, resp);
            case "getAllRoles" -> getAllRoles(req, resp);
            default -> showActive(req, resp);
        }

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String pathInfo = req.getPathInfo();

        // 处理 null 或空路径
        if (pathInfo == null || pathInfo.equals("/") || pathInfo.isEmpty()) {
            showActive(req, resp);
            return;
        }

        // 标准化路径（去除前导和尾随斜杠）
        String path = pathInfo.replaceAll("^/|/$", "");

        switch (path) {
            case "add" -> addUser(req, resp);
            case "changeState" -> changeState(req, resp);
            case "changeRole" -> changeRole(req, resp);
            default -> showActive(req, resp);
        }
    }

    public void changeState(HttpServletRequest req, HttpServletResponse resp) {
        Result result = null;
        // 要修改的用户状态
        int state = Integer.parseInt(req.getParameter("state"));
        // 要修改的用户ID
        int tarUserId = Integer.parseInt(req.getParameter("tarUserId"));

        try {
            if (userService.updateUserState(tarUserId, state) != 0) {
                result = new Result<>(200, "修改成功", state == 1 ? 0 : 1);
            } else {
                result = new Result<>(500, "修改失败", state == 1 ? 1 : 0);
            }
            String json = gson.toJson(result);
            resp.getWriter().println(json);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void changeRole(HttpServletRequest req, HttpServletResponse resp) {
        Result result = null;
        // 目标要修改成的角色ID和目标用户ID
        int tarRoleId = Integer.parseInt(req.getParameter("tarRoleId"));
        int tarUserId = Integer.parseInt(req.getParameter("tarUserId"));
        try {
            if (userService.updateUserRole(tarUserId, tarRoleId) != 0) {
                result = new Result(200, "修改成功", tarRoleId);
            } else {
                result = new Result(500, "修改失败", tarRoleId);
            }
            String json = gson.toJson(result);
            resp.getWriter().println(json);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void destroy() {
        super.destroy();
    }

    /**
     * 根据用户名查询用户
     *
     * @param req  请求
     * @param resp 响应
     */
    public void findByUsername(HttpServletRequest req, HttpServletResponse resp) {
        HttpSession session = req.getSession();
        String username = req.getParameter("username");
        PageHelper page = null;
        List<User> activeUsers = (List<User>) session.getAttribute("activeUsers");

        try {
            User targetUser = userService.findUserByUsername(username);
            if (activeUsers.stream().anyMatch(u -> u.getId() == targetUser.getId())) {
                String servletName = req.getPathInfo() == null ? req.getServletPath() : req.getServletPath() + req.getPathInfo();
                page = new PageHelper(List.of(targetUser), 1, PAGE_SIZE, 1, servletName, 1);

                req.setAttribute("page", page);
                req.getRequestDispatcher("/WEB-INF/views/showActive.jsp").forward(req, resp);
                return;
            }

            resp.getWriter().println("用户不存在");
            resp.sendRedirect(req.getContextPath() + req.getServletPath());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 根据ID查询用户
     *
     * @param req  请求
     * @param resp 响应
     */
    public void findById(HttpServletRequest req, HttpServletResponse resp) {
        HttpSession session = req.getSession();
        int id = Integer.parseInt(req.getParameter("id"));
        List<User> activeUsers = (List<User>) session.getAttribute("activeUsers");

        PageHelper page = null;
        // 获取当前页码
        int pageIndex = req.getParameter("pageIndex") == null ? 1 : Integer.parseInt(req.getParameter("pageIndex"));

        try {
            User targetUser = userService.findUserById(id);
            if (activeUsers.stream().anyMatch(u -> u.getId() == targetUser.getId())) {
                String servletName = req.getPathInfo() == null ? req.getServletPath() : req.getServletPath() + req.getPathInfo();
                page = new PageHelper(List.of(targetUser), pageIndex, PAGE_SIZE, 1, servletName, pageIndex);
                req.setAttribute("page", page);
                req.getRequestDispatcher("/WEB-INF/views/showActive.jsp").forward(req, resp);
                return;
            }

            resp.getWriter().println("用户不存在");
            resp.sendRedirect(req.getContextPath() + req.getServletPath());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 根据角色ID查询用户
     *
     * @param req  请求
     * @param resp 响应
     */
    public void findByRoleId(HttpServletRequest req, HttpServletResponse resp) {
        HttpSession session = req.getSession();
        User user = RedisUtil.getObject("session:" + session.getId(), User.class);
        if (user == null) {
            user = session.getAttribute("user") == null ? new User() : (User) session.getAttribute("user");
        }
        int roleId = user.getRoleId();
        int userId = user.getId();

        // 添加参数验证
        String roleSelectParam = req.getParameter("roleSelect");
        if (roleSelectParam == null || roleSelectParam.isEmpty()) {
            try {
                resp.sendRedirect(req.getContextPath() + "/usermanage"); // 重定向到默认页面
                return;
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        int roleSelect;
        try {
            roleSelect = Integer.parseInt(roleSelectParam);
        } catch (NumberFormatException e) {
            try {
                resp.sendRedirect(req.getContextPath() + "/usermanage"); // 参数格式错误时重定向
                return;
            } catch (IOException ioException) {
                throw new RuntimeException(ioException);
            }
        }

        PageHelper page = null;

        // 获取当前页码
        int pageIndex = req.getParameter("pageIndex") == null ? 1 : Integer.parseInt(req.getParameter("pageIndex"));

        try {
            page = userService.findPageByRoleId(roleId, userId, pageIndex, PAGE_SIZE, roleSelect);
            page.setServletName(req.getServletPath() + req.getPathInfo());

            // 需要携带的参数 页面信息、roleId、contentPage要显示的页面、menus导航
            try {
                List<Menu> menus = menuService.findMenusByRoleId(roleId);
                List<Menu> treeMenus = MenuTreeBuilder.buildMenuTree(menus);
                req.setAttribute("menus", treeMenus);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

            req.setAttribute("page", page);
            req.getRequestDispatcher("/WEB-INF/views/showActive.jsp").forward(req, resp);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 显示用户信息
     *
     * @param req  请求
     * @param resp 响应
     */
    public void showUserInfo(HttpServletRequest req, HttpServletResponse resp) {
        Result result = null;
        // 设置响应类型和编码
        resp.setContentType("application/json;charset=UTF-8");
        resp.setCharacterEncoding("UTF-8");

        try {
            System.out.println("进入showUserInfo");
            // 获取当前登陆的角色ID和用户ID
            System.out.println(req);
            System.out.println("当前用户角色ID：" + req.getParameter("roleId"));

            // 检查参数是否存在
            String roleIdStr = req.getParameter("roleId");
            String userIdStr = req.getParameter("userId");

            if (roleIdStr == null || roleIdStr.isEmpty()) {
                result = new Result(400, "缺少roleId参数", null);
                resp.getWriter().println(gson.toJson(result));
                return;
            }

            if (userIdStr == null || userIdStr.isEmpty()) {
                result = new Result(400, "缺少userId参数", null);
                resp.getWriter().println(gson.toJson(result));
                return;
            }

            int roleId = Integer.parseInt(roleIdStr);
            int userId = Integer.parseInt(userIdStr);
            var userInfo = userService.showDetailInfo(userId, roleId);
            System.out.println("用户信息：" + userInfo);

            if (userInfo != null) {
                result = new Result(200, "查询成功", userInfo);
            } else {
                result = new Result(404, "未找到用户信息", null);
            }
            System.out.println("返回结果：" + result);
            resp.getWriter().println(gson.toJson(result));
        } catch (NumberFormatException e) {
            result = new Result(400, "参数格式错误: " + e.getMessage(), null);
            try {
                resp.getWriter().println(gson.toJson(result));
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        } catch (Exception e) {
            result = new Result(500, "服务器内部错误: " + e.getMessage(), null);
            try {
                resp.getWriter().println(gson.toJson(result));
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }

    /**
     * 显示用户
     *
     * @param req  请求
     * @param resp 响应
     */
    public void showActive(HttpServletRequest req, HttpServletResponse resp) {
        HttpSession session = req.getSession();
        User user = RedisUtil.getObject("session:" + session.getId(), User.class);
        if (user == null) {
            user = session.getAttribute("user") == null ? new User() : (User) session.getAttribute("user");
        }
        int roleId = user.getRoleId();
        int userId = user.getId();

        // 获取当前页码
        int pageIndex = req.getParameter("pageIndex") == null ? 1 : Integer.parseInt(req.getParameter("pageIndex"));
        PageHelper<User> page = null;
        try {
            // 获取显示用户集合
            page = switch (roleId) {
                // 1 讲师 - 只能看到学生
                case 1 -> userService.showPageByOwnClazz(userId, pageIndex, PAGE_SIZE);
                // 2 教务 - 能看到讲师、教务、学生、辅导员
                case 2 -> userService.findPageByRoleIds(pageIndex, PAGE_SIZE, 1, 2, 4, 5, 0, 0, 0);
                // 3 超级管理员 和 7 校长 - 能看到所有用户
                case 3, 7 -> userService.findPageByRoleIds(pageIndex, PAGE_SIZE, 1, 2, 3, 4, 5, 6, 7);
                // 4 学生 - 不能看到其他用户
                case 4 -> new PageHelper<>(new ArrayList<>(), pageIndex, PAGE_SIZE, 0, "/usermanage/", 0);
                // 5 辅导员 - 只能看到学生
                case 5 -> userService.findPageByRoleIds(pageIndex, PAGE_SIZE, 4, 0, 0, 0, 0, 0, 0);
                // 6 学院院长 - 能看到讲师、教务、辅导员
                case 6 -> userService.findPageByRoleIds(pageIndex, PAGE_SIZE, 1, 2, 5, 0, 0, 0, 0);
                default -> page;
            };

            if (page != null) {
                String servletName = req.getPathInfo() == null ? req.getServletPath() : req.getServletPath() + req.getPathInfo();
                page.setServletName(servletName);
            }

            req.setAttribute("page", page);
            req.getRequestDispatcher("/WEB-INF/views/showActive.jsp").forward(req, resp);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 用户信息下拉列表
     *
     * @param req  请求
     * @param resp 响应
     */
    public void getRoleList(HttpServletRequest req, HttpServletResponse resp) {
        resp.setContentType("application/json;charset=UTF-8");
        resp.setCharacterEncoding("UTF-8");

        HttpSession session = req.getSession();
        User user = RedisUtil.getObject("session:" + session.getId(), User.class);
        int roleId = 0;
        if (user != null) {
            roleId = user.getRoleId();
        }

        List<Role> roles = new ArrayList<>();
        try {
            switch (roleId) {
                // 超级管理员和校长 - 可以添加所有角色
                case 3, 7:
                    Role role1 = roleService.findRoleById(1); // 讲师
                    Role role2 = roleService.findRoleById(4); // 学生
                    Role role3 = roleService.findRoleById(2); // 教务
                    Role role4 = roleService.findRoleById(5); // 辅导员
                    Role role5 = roleService.findRoleById(6); // 学院院长
                    if (role1 != null) roles.add(role1);
                    if (role2 != null) roles.add(role2);
                    if (role3 != null) roles.add(role3);
                    if (role4 != null) roles.add(role4);
                    if (role5 != null) roles.add(role5);
                    break;
                // 学院院长 - 可以添加讲师、教务、辅导员、学生
                case 6:
                    Role r1 = roleService.findRoleById(1); // 讲师
                    Role r2 = roleService.findRoleById(4); // 学生
                    Role r3 = roleService.findRoleById(2); // 教务
                    Role r4 = roleService.findRoleById(5); // 辅导员
                    if (r1 != null) roles.add(r1);
                    if (r2 != null) roles.add(r2);
                    if (r3 != null) roles.add(r3);
                    if (r4 != null) roles.add(r4);
                    break;
                // 讲师 - 只能添加自己班级的学生
                case 1:
                    Role role = roleService.findRoleById(4);
                    if (role != null) roles.add(role);
                    break;
                // 教务、辅导员、学生 - 无添加权限或只能添加特定角色
                default:
                    break;
            }

            Result<List<Role>> result = new Result<>(200, "查询成功", roles);
            String resultJson = gson.toJson(result);
            System.out.println("返回数据: " + resultJson); // 调试输出
            resp.getWriter().println(resultJson);
        } catch (Exception e) {
            e.printStackTrace();
            try {
                Result<List<Role>> errorResult = new Result<>(500, "服务器内部错误: " + e.getMessage(), null);
                resp.getWriter().println(gson.toJson(errorResult));
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }

    public void getUserList(HttpServletRequest req, HttpServletResponse resp) {
        HttpSession session = req.getSession();
        User user = RedisUtil.getObject("session:" + session.getId(), User.class);
        int roleId = 0;
        if (user != null) {
            roleId = user.getRoleId();
        }

        List<?> users = new ArrayList<>();
        try {
            // 设置响应内容类型
            resp.setContentType("application/json;charset=UTF-8");
            resp.setCharacterEncoding("UTF-8");

            if (roleId == 3 || roleId == 7) { // 超级管理员和校长
                String selectedRoleIdStr = req.getParameter("selectedRoleId");
                if (selectedRoleIdStr != null && !selectedRoleIdStr.isEmpty()) {
                    int selectedRoleId = Integer.parseInt(selectedRoleIdStr);
                    //选择角色为老师
                    if (selectedRoleId == 1) {
                        users = teacherService.findNonUserTeacher();
                    }
                    //选择角色为学生
                    else if (selectedRoleId == 4) {
                        users = studentService.findNonUserStu();
                    }
                }
            } else if (roleId == 1) { // 讲师
                int infoId = user.getInfoId();
                users = studentService.findNonUserStu(infoId);
            } else if (roleId == 6) { // 学院院长
                // 学院院长可以查看讲师(1)、教务(2)、辅导员(5)
                String selectedRoleIdStr = req.getParameter("selectedRoleId");
                if (selectedRoleIdStr != null && !selectedRoleIdStr.isEmpty()) {
                    try {
                        int selectedRoleId = Integer.parseInt(selectedRoleIdStr);
                        // 讲师
                        if (selectedRoleId == 1) {
                            users = teacherService.findNonUserTeacher();
                        }
                        // 教务
                        else if (selectedRoleId == 2) {
                            //可以看到非用户的教师、辅导员和学生
                            users = new ArrayList<>();
                        }
                        // 辅导员
                        else if (selectedRoleId == 5) {
                            users = studentService.findNonUserStu();
                        }
                    } catch (NumberFormatException e) {
                        // 参数格式错误处理
                        Result<List<?>> errorResult = new Result<>(400, "角色ID格式错误", new ArrayList<>());
                        resp.getWriter().write(gson.toJson(errorResult));
                        return;
                    }
                } else {
                    users = new ArrayList<>();
                }
            }

            Result<List<?>> result = new Result<>(200, "查询成功", users);
            String resultJson = gson.toJson(result);
            resp.getWriter().write(resultJson);
        } catch (NumberFormatException e) {
            try {
                Result<List<?>> result = new Result<>(400, "参数格式错误", new ArrayList<>());
                resp.getWriter().write(gson.toJson(result));
            } catch (IOException ioException) {
                throw new RuntimeException(ioException);
            }
        } catch (Exception e) {
            try {
                Result<List<?>> result = new Result<>(500, "服务器内部错误: " + e.getMessage(), new ArrayList<>());
                resp.getWriter().write(gson.toJson(result));
            } catch (IOException ioException) {
                throw new RuntimeException(ioException);
            }
        }
    }


    /**
     * 添加用户
     *
     * @param req
     * @param resp
     * @throws Exception
     */
    public void addUser(HttpServletRequest req, HttpServletResponse resp) {
        try {
            //表单数据 用户名(phone) 初始密码
            String username = req.getParameter("username");
            String password = req.getParameter("password");
            //要添加的角色id
            int submitRoleId = Integer.parseInt(req.getParameter("roleOption"));
            //要添加的用户id
            int submitInfoId = Integer.parseInt(req.getParameter("userOption"));

            if ((!username.isEmpty()) && submitInfoId != 0 && submitRoleId != 0) {
                //执行添加用户
                if (userService.insertUser(new User(username, password, submitRoleId, submitInfoId)) != 0) {
                    Result result = new Result(200, "添加成功", null);
                    resp.getWriter().println(gson.toJson(result));
                } else {
                    Result result = new Result(500, "添加失败", null);
                    resp.getWriter().println(gson.toJson(result));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void deleteUser(HttpServletRequest req, HttpServletResponse resp) {
        try {
            int userId = Integer.parseInt(req.getParameter("userId"));
            if (userService.deleteUserById(userId) != 0) {
                Result result = new Result(200, "删除成功", null);
                resp.getWriter().println(gson.toJson(result));
                return;
            }

            Result result = new Result(500, "删除失败", null);
            resp.getWriter().println(gson.toJson(result));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取所有角色列表
     */
    public void getAllRoles(HttpServletRequest req, HttpServletResponse resp) {
        Result result = null;
        resp.setContentType("application/json;charset=UTF-8");

        try {
            // 获取所有角色
            List<Role> roles = roleService.findAllRoleInfo();
            result = new Result(200, "查询成功", roles);
            resp.getWriter().println(gson.toJson(result));
        } catch (Exception e) {
            result = new Result(500, "查询失败: " + e.getMessage(), null);
            try {
                resp.getWriter().println(gson.toJson(result));
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }
}
